iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
Rust

Rust 後端入門系列 第 21

Day 21 Axum 專案整合 CORS/Tracing

  • 分享至 

  • xImage
  •  

CORS

  • 作用:控制瀏覽器端跨域請求是否被允許(preflight OPTIONS 與 Access-Control-Allow-* header)。
  • 為什麼要做:
    • 若前端與 API 不同 origin(網域/port/協議),瀏覽器會阻擋未授權的跨域請求。
    • CORS 也是限制哪些網站可從瀏覽器濫用你的 API 的一層防線(注意:只對瀏覽器生效,不能當作完整授權機制)。
  • 優點:
    • 允許前端正常呼叫 API(必要);在生產精準設定可減少被第三方網頁濫用。
  • 實務重點:
    • 開發可短暫允許 Any,但生產務必列明允許 origin(或從環境變數讀取清單)。
    • 若使用 cookie-based auth 並跨域:必須指定單一 origin 且啟用 allow_credentials(true)(不能搭配 Any)。
    • 指定允許的 methods、headers、預檢 max_age(可減少預檢頻率)。
  • 風險與注意:
    • 不要把 CORS 當作授權機制;需與身份驗證、rate limit、server-side 檢查一起使用。

Tracing

  • 作用:記錄系統事件、請求生命週期(建立 span、紀錄 latency/status)、串連分散式請求(request_id / span)。
  • 為什麼要做:
    • 生產快速定位錯誤、追蹤慢查詢與高延遲,並做容量與 SLA 評估。
  • 優點:
    • 結構化日誌便於集中式搜尋/聚合(ELK / Loki / Datadog);span 可以把同一請求在多個模組的 log 關聯起來。
  • 實務重點:
    • 用 tracing + tracing_subscriber;HTTP 層用 tower-http::trace::TraceLayer 自動產生 request span。
    • 使用 EnvFilter(或 RUST_LOG)在不同環境調整 log level。
    • 在 TraceLayer 設定不包含 headers(include_headers(false))或在 make_span 手動遮罩 Authorization/Cookie/password 等敏感欄位。
    • 若要匯入 observability,考慮 JSON 格式輸出或接 OpenTelemetry。

中間件順序與設計原則

  • 原則:把需要早期短路的安全/保護 layer(例如 rate limit、auth)放前面;trace 放在能完整包覆處理流程的位置;CORS 要能回應 preflight(通常放在 handler 之前)。
  • 常見順序範例:TraceLayer -> Rate limit -> CORS -> Compression/Timeout -> Extensions(shared state)。
  • 不同順序會改變哪些資訊被記錄、哪些請求會被短路,設計時要先列出你的短路/記錄需求再決定順序。

資安建議

  • 日誌不要記 raw body 與敏感欄位,生產環境僅在必要時開 debug。
  • CORS 設定從環境變數讀取,方便在不同環境使用不同策略。
  • 若高併發或大量 tracing,檢查 tracing_subscriber 的輸出 I/O 是否會成為瓶頸(建議輸出到非同步/集中式系統或用 batch)。
  • 若你要做 re-auth 或 rehash-on-login,記得不要在 log 中寫密碼或雜湊值。

範例

在 Cargo.toml 補上:

tower-http = { version = "0.6", features = ["cors", "trace"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
http = "1.3"

在 main.rs 新增的 imports 與中間件設定:

新增 imports(在檔案頂端):

use tower_http::cors::{CorsLayer, Any, AllowOrigin};
use tower_http::trace::{TraceLayer, DefaultMakeSpan, DefaultOnResponse};
use tracing_subscriber::{EnvFilter, fmt};
use tracing::Level;
use http::{Method, HeaderValue};
use tracing_subscriber::prelude::*;

在 main 加入 tracing 初始化(放在 dotenv().ok() 之後):

let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
tracing_subscriber::registry()
    .with(env_filter)
    .with(fmt::layer().with_target(false)) // 或 .json() 輸出 JSON
    .init();

建立 CorsLayer 與 TraceLayer:

let localhost = HeaderValue::from_static("http://localhost:5173");
	
	let cors = CorsLayer::new()
		.allow_origin(AllowOrigin::exact(localhost))
		.allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE, Method::OPTIONS])
		.allow_headers(Any)
		.max_age(std::time::Duration::from_secs(600));

let trace = TraceLayer::new_for_http()
    .make_span_with(DefaultMakeSpan::new().include_headers(false)) // 不自動包含 headers,避免敏感資訊
    .on_response(DefaultOnResponse::new().level(Level::INFO));

把 layer 套到 Router:

let app = Router::new()
    // ...
    .layer(trace)
    .layer(cors)
    .layer(Extension(pool))
    .layer(Extension(redis_conn));

備註

  • production 時請把 HeaderValue::from_static("http://localhost:5173"); 改為 HeaderValue::from_static("https://your-frontend.com") 或把複數 origin 從環境變數解析成清單後動態建立 policy。
  • 若需要在 trace span 中加入 request_id,可在 make_span callback 讀 header "x-request-id"(若無則生成)並加入 span;同時在 response header 回寫該 id。

在 .env 加入:

RUST_LOG=debug

開啟詳細DEBUG紀錄

測試

OPTIONS http://127.0.0.1:3000/users

 HTTP/1.1 200 OK
 vary: origin, access-control-request-method, access-control-request-headers
 access-control-allow-methods: GET,POST,PUT,DELETE,OPTIONS
 access-control-allow-headers: *
 access-control-max-age: 600
 access-control-allow-origin: http://localhost:5173
 allow: POST,GET,HEAD
 content-length: 0
 date: Sun, 05 Oct 2025 00:56:25 GMT

檢查回應是否有 Access-Control-Allow-Origin / Allow-Methods

重點結論

  • CORS:讓瀏覽器能正確跨域呼叫 API;生產環境要精確限制 origin 與 credential 行為。
  • Tracing:提供結構化、可串連的請求級別觀測(method、uri、status、latency、request_id),方便除錯與監控;同時必須避免在日誌中洩漏敏感資訊。

上一篇
Day 20 Axum與密碼安全
下一篇
Day 22 Axum專案導入 Validator
系列文
Rust 後端入門25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言